#include "OpenFile.h"
#include "const.h"
#include <algorithm>
#include <cassert>

OpenFile::OpenFile(FileSystem* filesystem, Inode* inode, std::string name) {
	this->name = name;
	iopos = 0;
	this->filesystem = filesystem;
	this->inode = inode;
	usecount = 1;
}

OpenFile::~OpenFile() {
}

int OpenFile::read(char buffer[], int count) {
    int bytes_read = 0;

	while (count > 0) {
		int offset = iopos % DBLKSIZ;
		int chunk = min(count, DBLKSIZ - offset);

		// init filesize en bytes left
		int filesize = inode->getFileSize();
		int bytes_left = filesize - iopos;

		// check of eind of file al bereikt is ...
		if (iopos >= filesize)
			break;

		// ... of eind of file met deze chunk bereikt wordt
		if (chunk > bytes_left)
			chunk = bytes_left;
		
		// schrijf data to buffer
		writeDataToBuffer(buffer, count, offset, chunk);

		// variablen wijzigen
		count -= chunk;
		iopos += chunk;
        bytes_read += chunk;
	}

	return bytes_read;
}

void OpenFile::writeDataToBuffer(char buffer[], int count, int offset, int chunk) {
	long blocknummer = inode->getBlocknummer(iopos - offset);
	byte* chunk_data = filesystem->getBlok(blocknummer)->getBytes();

	for (int i = 0; i < chunk; ++i) {
		buffer[i] = chunk_data[i];
    }
}

int OpenFile::lseek(long offset, int whence) {
	assert(whence >= 0);
	assert(whence <= 2);

	int filesize = inode->getFileSize();
	int pos = 0;
	
	switch (whence) {
		case SEEK_SET: pos = 0; break;
		case SEEK_CUR: pos = iopos; break;
		case SEEK_END: pos = filesize; break;
	}
	
	int new_pos = 0;
	if (new_pos > filesize || new_pos < 0) {
		return -1;
	}

	iopos = new_pos;
	return new_pos;
}

void OpenFile::toString() {
	inode->toString();
}

std::string OpenFile::getName() {
	return name;
}

Inode* OpenFile::getInode() {
	return inode;
}

int OpenFile::getUsecount() {
	return usecount;
}

void OpenFile::usecountIncrement() {
	usecount++;
}

void OpenFile::close() {
	assert(usecount > 0);
	usecount--;
}
